package com.open.cloud.rbac.utils;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.lang3.StringUtils;

import javax.net.ssl.X509TrustManager;
import java.io.File;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 　　　　　　　　┏┓　　　┏┓+ +
 * 　　　　　　　┏┛┻━━━┛┻┓ + +
 * 　　　　　　　┃　　　　　　　┃
 * 　　　　　　　┃　　　━　　　┃ ++ + + +
 * 　　　　　　 ████━████ ┃+
 * 　　　　　　　┃　　　　　　　┃ +
 * 　　　　　　　┃　　　┻　　　┃
 * 　　　　　　　┃　　　　　　　┃ + +
 * 　　　　　　　┗━┓　　　┏━┛
 * 　　　　　　　　　┃　　　┃
 * 　　　　　　　　　┃　　　┃ + + + +
 * 　　　　　　　　　┃　　　┃　　　　   @Author: wang.yangtx　@Date:  2019/4/26 15:10
 * 　　　　　　　　　┃　　　┃ + 　　　　神兽保佑,代码无bug
 * 　　　　　　　　　┃　　　┃
 * 　　　　　　　　　┃　　　┃　　+
 * 　　　　　　　　　┃　 　　┗━━━┓ + +
 * 　　　　　　　　　┃ 　　　　　　　┣┓
 * 　　　　　　　　　┃ 　　　　　　　┏┛
 * 　　　　　　　　　┗┓┓┏━┳┓┏┛ + + + +
 * 　　　　　　　　　　┃┫┫　┃┫┫
 * 　　　　　　　　　　┗┻┛　┗┻┛+ + + +
 */
@Slf4j
public class HttpUtils {
    private static OkHttpClient okHttpClient = new OkHttpClient.Builder().connectTimeout(60, TimeUnit.SECONDS)      //设置连接超时
            .readTimeout(60, TimeUnit.SECONDS)         //设置读超时
            .writeTimeout(60, TimeUnit.SECONDS)        //设置写超时
            .retryOnConnectionFailure(true)            //是否自动重连
//            .connectionPool(new ConnectionPool(5, 6, TimeUnit.MINUTES))
            .retryOnConnectionFailure(true)            //是否自动重连
//            .connectionPool(new ConnectionPool(5, 6, TimeUnit.MINUTES))
            .sslSocketFactory(SSLSocketClient.getSSLSocketFactory(), new X509TrustManager() {
                @Override
                public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {

                }

                @Override
                public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {

                }

                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[]{};
                }
            }).hostnameVerifier((hostname, session) -> true)
            .build();

    public static String postForm(String url, Map<String, Object> paramMap, Map<String, String> header, boolean isFile) throws IOException {
        RequestBody body = null;
        if (!isFile) {
            FormBody.Builder builder = new FormBody.Builder();
            for (Map.Entry<String, Object> entry : paramMap.entrySet()) {
                builder.add(entry.getKey(), Objects.toString(entry.getValue(), ""));
            }
            body = builder.build();
        } else {
            MultipartBody.Builder builder = new MultipartBody.Builder();
            builder.setType(MultipartBody.FORM);
            for (Map.Entry<String, Object> entry : paramMap.entrySet()) {
                Object value = entry.getValue();
                if (value instanceof File) {
                    File file = (File) value;
                    builder.addFormDataPart(entry.getKey(), file.getName(), RequestBody.create(MediaType.parse("application/octet-stream"), file));
                } else {
                    builder.addFormDataPart(entry.getKey(), entry.getValue().toString());
                }
            }
            body = builder.build();
        }
        Request.Builder requestBuiler = new Request.Builder();
        addHeader(header, requestBuiler);
        Request request = requestBuiler
                .url(url)
                .post(body)
                .build();

        Call call = okHttpClient.newCall(request);
        Response response = call.execute();
        return response.body().string();
    }

    public static Map<String, Object> postJSON(String url, String json, Map<String, String> header) {
        Map<String, Object> responseMap = new HashMap<>();
        try {
            Response response = json(url, json, header);
            responseMap.put("code", response.code());
            responseMap.put("header", response.headers());
            responseMap.put("body", response.body().string());
            log.info(">>>>responseString={}", responseMap);
        } catch (Exception e) {
            log.error("提交JSON异常", e);
            throw new RuntimeException(e);
        }
        return responseMap;
    }

    public static Map<String, Object> postSjJSON(String url, String json) {
        Map<String, Object> responseMap = new HashMap<>();
        try {
            Response response = sjJson(url, json);
            responseMap.put("code", response.code());
            responseMap.put("body", response.body().string());
            log.info(">>>>responseString={}", responseMap);
        } catch (Exception e) {
            log.error("提交JSON异常", e);
            throw new RuntimeException(e);
        }
        return responseMap;
    }

    public static String postJSON(String url, String json) {
        String responseString = "";
        try {
            Response response = json(url, json, new HashMap<>());
            responseString = response.body().string();
            log.info(">>>>>>>>response={}", responseString);
        } catch (Exception e) {
            log.error("调用服务异常", e);
            throw new RuntimeException(String.format(">>>>>>>>调用服务异常:%s |#| response:%s", e.getMessage(), responseString));
        }
        return responseString;
    }

    private static Response json(String url, String json, Map<String, String> header) throws Exception {
        RequestBody requestBody = FormBody.create(json, MediaType.parse("application/json; charset=utf-8"));
        //.addHeader("Content-Type","application/json;charset=UTF-8").addHeader("Accept", "application/json;charset=UTF-8")
        log.info(">>>>url={},json={}", url, json);
        final Request.Builder builder = new Request.Builder();
        addHeader(header, builder);
        builder.addHeader("Content-Type", "application/json;charset=utf8");
        Request request = builder.url(url).post(requestBody).build();
        Call call = okHttpClient.newCall(request);
        Response response = call.execute();
        final int code = response.code();
        log.info(">>>>url={},StatusCode={}", url, code);
//        if (code >= 300 || code < 200) {
//            throw new RuntimeException("请求失败 StatusCode=" + code);
//        }
        return response;
    }

    private static Response sjJson(String url, String json) throws Exception {
        //RequestBody requestBody = FormBody.create(json, MediaType.parse("application/x-www-form-urlencoded; charset=utf-8"));
        //.addHeader("Content-Type","application/json;charset=UTF-8").addHeader("Accept", "application/json;charset=UTF-8")
        log.info(">>>>url={},json={}", url, json);
        final Request.Builder builder = new Request.Builder();
        //addHeader(header, builder);
        builder.addHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf8");
        builder.method("post", null);
        Request request = builder.url(url).build();
        Call call = okHttpClient.newCall(request);
        Response response = call.execute();
        final int code = response.code();
        log.info(">>>>url={},StatusCode={}", url, code);
//        if (code >= 300 || code < 200) {
//            throw new RuntimeException("请求失败 StatusCode=" + code);
//        }
        return response;
    }

    public static Map<String, Object> get(String url, Map<String, String> header) throws IOException {
        Map<String, Object> responseMap = new HashMap<>();
        final Request.Builder builder = new Request.Builder();
        addHeader(header, builder);
        builder.addHeader("Content-Type", "application/json;charset=utf8");
        Request request = builder.url(url).get().build();
        Call call = okHttpClient.newCall(request);
        Response response = call.execute();
        final int code = response.code();
        log.info(">>>>url={},code={}", url, code);
        if (code >= 300 || code < 200) {
            throw new RuntimeException("请求失败 StatusCode=" + code);
        }
        String responseString = response.body().string();
        log.info(">>>>responseString={}", responseString);
        responseMap.put("body", responseString);
        responseMap.put("code", response.code());
        return responseMap;
    }

    public static Map<String, Object> delete(String url, String json, Map<String, String> header) throws IOException {
        log.info(">>>>url={},json={}", url, json);
        RequestBody requestBody = null;
        if (json != null) {
            requestBody = FormBody.create(json, MediaType.parse("application/json; charset=utf-8"));
        }
        log.info(">>>>url={},json={}", url, json);
        Map<String, Object> responseMap = new HashMap<>();
        final Request.Builder builder = new Request.Builder();
        addHeader(header, builder);
        builder.addHeader("Content-Type", "application/json;charset=utf8");
        Request request = builder.url(url).delete(requestBody).build();
        Call call = okHttpClient.newCall(request);
        Response response = call.execute();
        final int code = response.code();
        log.info(">>>>url={},code={}", url, code);
        if (code >= 300 || code < 200) {
            throw new RuntimeException("请求失败 StatusCode=" + code);
        }
        String responseString = response.body().string();
        log.info(">>>>responseString={}", responseString);
        responseMap.put("code", response.code());
        responseMap.put("body", responseString);
        return responseMap;
    }

    public static Map<String, Object> put(String url, String json, Map<String, String> header) throws IOException {
        Map<String, Object> responseMap = new HashMap<>();
        final Request.Builder builder = new Request.Builder();
        addHeader(header, builder);
        builder.addHeader("Content-Type", "application/json;charset=utf8");
        RequestBody requestBody = FormBody.create(json, MediaType.parse("application/json; charset=utf-8"));
        Request request = builder.url(url).put(requestBody).build();
        Call call = okHttpClient.newCall(request);
        Response response = call.execute();
        final int code = response.code();
        log.info(">>>>url={},code={}", url, code);
        if (code >= 300 || code < 200) {
            throw new RuntimeException("请求失败 StatusCode=" + code);
        }
        String responseString = response.body().string();
        log.info(">>>>responseString={}", responseString);
        responseMap.put("code",code);
        responseMap.put("body", responseString);
        return responseMap;
    }

    private static void addHeader(Map<String, String> header, Request.Builder builder) {
        if (header != null) {
            final Iterator<String> iterator = header.keySet().iterator();
            while (iterator.hasNext()) {
                String name = iterator.next();
                String value = header.get(name);
                if (StringUtils.isNotBlank(value)) {
                    builder.addHeader(name, value);
                }
                log.info(">>>>header name={},value={}", name, value);
            }
        }
    }

    public static JSONObject postJSONObj(String url, String json, Map<String, String> header) {
        //Map<String, Object> responseMap = new HashMap<>();
        JSONObject responseObj = new JSONObject();
        try {
            Response response = json(url, json, header);
            responseObj.put("code", response.code());
            responseObj.put("header", response.headers());
            JSONObject jsonObject = JSON.parseObject(response.body().string());
            responseObj.put("body", jsonObject);
            log.info(">>>>responseString={}", responseObj);
        } catch (Exception e) {
            log.error("提交JSON异常", e);
            throw new RuntimeException(e);
        }
        return responseObj;
    }

}
